package org.bookie.framework.components;

import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import org.apache.tapestry.IActionListener;
import org.apache.tapestry.IDynamicInvoker;
import org.apache.tapestry.annotations.InjectObject;
import org.apache.tapestry.event.PageBeginRenderListener;
import org.apache.tapestry.event.PageEvent;
import org.apache.tapestry.form.BeanPropertySelectionModel;
import org.apache.tapestry.form.IPropertySelectionModel;
import org.apache.tapestry.listener.ListenerInvoker;
import org.bookie.framework.CommonBaseComponent;
import org.bookie.model.Category;
import org.bookie.model.Event;
import org.bookie.model.Event.State;
import org.bookie.model.services.CategoryDAO;

public abstract class EventForm extends CommonBaseComponent implements PageBeginRenderListener, IDynamicInvoker {

    public void doListener(){
		if (getDelegate().getHasErrors()) {
			if(getCancel()!=null){
				getListenerInvoker().invokeListener(getCancel(), this, getRequestCycle());
			}
			return;
		}
		Date dateTime = getDateTime(getEvent().getEndDate(),  getTime());
		getEvent().setEndDate(dateTime);
		State state = isActivated()?State.ACTIVE:State.INACTIVE;
		getEvent().setState(state);
        getListenerInvoker().invokeListener(getListener(), this, getRequestCycle());
    }
    
	/**
	 * Aggregates the date and the time to datetime
	 * @return instance of Date
	 */
	private Date getDateTime(Date date, Date time) {
		GregorianCalendar timeCal = new GregorianCalendar();
		timeCal.setTime(time);

		GregorianCalendar dateCal = new GregorianCalendar();
		dateCal.setTime(date);
		dateCal.set(Calendar.HOUR_OF_DAY, timeCal.get(Calendar.HOUR_OF_DAY));
		dateCal.set(Calendar.MINUTE, timeCal.get(Calendar.MINUTE));
		return dateCal.getTime();
	}
    
    public abstract IActionListener getListener();
    
    public abstract IActionListener getCancel();
    
    @InjectObject("infrastructure:listenerInvoker")
    public abstract ListenerInvoker getListenerInvoker();
    
	/**
	 * This method takes care that time parameter is filled with value
	 */
	public void pageBeginRender(PageEvent event) {
		if(getEvent()!=null){
			setTime(getEvent().getEndDate());
			setActivated(getEvent().getState().value()==Event.State.ACTIVE.value());
		}
		setCategories(new BeanPropertySelectionModel(
				getCategoryDAO().findAll(), "name"));
	}
    
    public List getUpdateComponents(){
        return Arrays.asList(new Object[] {getClientId()});
    }

    public boolean isAsync(){
        return true;
    }

    public boolean isJson(){
        return false;
    }
    
	public abstract Event getEvent();
	/**
	 * Injected {@link CategoryDAO} service.
	 * @return instance of CategoryDAO
	 */
	@InjectObject("service:bookie.model.CategoryDAO")
	public abstract CategoryDAO getCategoryDAO();
	
    public abstract Date getTime();
    public abstract void setTime(Date date);
    
    public abstract boolean isActivated();
    public abstract void setActivated(boolean activated);
    
	/**
	 * Get the {@link Category} selection model
	 * @return instance of IPropertySelectionModel
	 */
	public abstract IPropertySelectionModel getCategories();
	
	/**
	 * Set the {@link Category} selection model
	 * @param model model to set
	 */
	public abstract void setCategories(IPropertySelectionModel model);
}
